// PatMan.cpp : implementation file
//

#include "StdAfx.h"
#include "../Frame/GYWalkAidApp.h"
#include "PatMan.h"
#include "../Common/LinkInputNode.h"
#include "../Common/CommonDef.h"
#include "../Common/LinkEdit.h"
#include "../Common/LinkComboBox.h"
#include "../Common/CommonFun.h"
#include "../Common/GYDataSet.h"
#include "PatientSelectDlg.h"
#include "PatientInfoEditDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

static INPUT_FIELD_INFO s_InputFieldArray[] = 
{
	{NULL,		IBT_NoneType,	FALSE,	FALSE,	_T("MedicalRecordNo"),		ftString,	FALSE,	IDS_PAT_FIELD_MRN,				10,		CPatMan::KeyFieldsCheck,		CPatMan::LostFocusCheck	},
	{NULL,		IBT_NoneType,	FALSE,	FALSE,	_T("Name"),					ftString,	FALSE,	IDS_PAT_FIELD_NAME,				12,		CPatMan::KeyFieldsCheck,		CPatMan::LostFocusCheck	},
	{NULL,		IBT_NoneType,	FALSE,	FALSE,	_T("SerialNo"),				ftNumber,	FALSE,	IDS_PAT_FIELD_SN,				10,		CPatMan::KeyFieldsCheck,		CPatMan::LostFocusCheck	},
	{NULL,		IBT_NoneType,	FALSE,	FALSE,	_T("Gender"),				ftNumber,	FALSE,	IDS_PAT_FIELD_GERDER,			10,		NULL,							NULL					},
	{NULL,		IBT_NoneType,	FALSE,	FALSE,	_T("Stature"),				ftNumber,	TRUE,	IDS_PAT_FIELD_STATURE,			10,		NULL,							NULL					},
	{NULL,		IBT_NoneType,	FALSE,	FALSE,	_T("Weight"),				ftNumber,	TRUE,	IDS_PAT_FIELD_WEIGHT,			10,		NULL,							NULL					},
	{NULL,		IBT_NoneType,	FALSE,	FALSE,	_T("DateOfBirth"),			ftDate,		FALSE,	IDS_PAT_FIELD_DATEOFBIRTH,		10,		CPatMan::DateOfBirthCheck,		CPatMan::DateOfBirthCheck},
	{NULL,		IBT_NoneType,	FALSE,	FALSE,	_T("PhoneNo"),				ftString,	TRUE,	IDS_PAT_FIELD_PHONE_NO,			20,		NULL,							NULL					},
	{NULL,		IBT_NoneType,	TRUE,	FALSE,	_T("FirstClinicDoctor"),	ftString,	FALSE,	IDS_PAT_FIELD_1ST_DOCTOR,		12,		NULL,							NULL					},
	{NULL,		IBT_NoneType,	FALSE,	FALSE,	_T("FirstClinicTime"),		ftDate,		FALSE,	IDS_PAT_FIELD_FIRSTCLINICDATE,	10,		NULL,							NULL					},
	{NULL,		IBT_NoneType,	FALSE,	FALSE,	_T("HomeAddress"),			ftString,	TRUE,	IDS_PAT_FIELD_HOMEADDRESS,		60,		NULL,							NULL					},
	{NULL,		IBT_NoneType,	FALSE,	FALSE,	_T("ClinicalDiagnosis"),	ftString,	FALSE,	IDS_PAT_FIELD_DIAG_RESULT,		60,		NULL,							NULL					},
};



/////////////////////////////////////////////////////////////////////////////
// CPatMan dialog

CPatMan::CPatMan(CWnd* pParent) : CDialog(CPatMan::IDD, pParent)
,  m_edtMedicaRecordNo(&s_InputFieldArray[0])
,			 m_edtName(&s_InputFieldArray[1])
,		 m_edtSerialNo(&s_InputFieldArray[2])
,		   m_cmbGender(&s_InputFieldArray[3])
,		  m_edtStature(&s_InputFieldArray[4])
,		   m_edtWeight(&s_InputFieldArray[5])
,	  m_edtDateOfBirth(&s_InputFieldArray[6])
,		  m_edtPhoneNo(&s_InputFieldArray[7])
, m_edt1stClinicDoctor(&s_InputFieldArray[8])
,	m_edt1stClinicDate(&s_InputFieldArray[9])
,	  m_edtHomeAddress(&s_InputFieldArray[10])
,	  m_edtClincalDiag(&s_InputFieldArray[11])
{
	//{{AFX_DATA_INIT(CPatMan)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT

	m_bPatInfoSaved = TRUE;
}


void CPatMan::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CPatMan)
	DDX_Control(pDX, IDC_COMBO_GENDER, m_cmbGender);
	DDX_Control(pDX, IDC_EDIT_CLINICAL_DIAG, m_edtClincalDiag);
	DDX_Control(pDX, IDC_EDIT_HOME_ADDRESS, m_edtHomeAddress);
	DDX_Control(pDX, IDC_EDIT_1ST_CLINIC_TIME, m_edt1stClinicDate);
	DDX_Control(pDX, IDC_EDIT_1ST_CLINIC_DOCTOR, m_edt1stClinicDoctor);
	DDX_Control(pDX, IDC_EDIT_DATEOFBIRTH, m_edtDateOfBirth);
	DDX_Control(pDX, IDC_EDIT_PHONENO, m_edtPhoneNo);
	DDX_Control(pDX, IDC_EDIT_WEIGHT, m_edtWeight);
	DDX_Control(pDX, IDC_EDIT_STATURE, m_edtStature);
	DDX_Control(pDX, IDC_EDIT_SERIAL_NO, m_edtSerialNo);
	DDX_Control(pDX, IDC_EDIT_NAME, m_edtName);
	DDX_Control(pDX, IDC_EDIT_MEDICAL_CARD_NO, m_edtMedicaRecordNo);
	DDX_Control(pDX, IDB_BITMAP_BUTTON_CLOSE, m_btnClose);
	DDX_Control(pDX, IDC_TAB_TREAT_INFO, m_tabTreat);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CPatMan, CDialog)
	//{{AFX_MSG_MAP(CPatMan)
	ON_NOTIFY(TCN_SELCHANGE, IDC_TAB_TREAT_INFO, OnSelchangeTabTreatInfo)
	ON_BN_CLICKED(IDB_BITMAP_BUTTON_CLOSE, OnBitmapClose)
	ON_BN_CLICKED(IDB_NEW_PATIENT_INFO, OnNewPatientInfo)
	ON_BN_CLICKED(IDB_EDIT_PATIENT_INFO, OnEditPatientInfo)
	ON_BN_CLICKED(IDB_CANCEL_PATIENT_INFO, OnCancelPatientInfo)
	ON_NOTIFY(TCN_SELCHANGING, IDC_TAB_TREAT_INFO, OnSelchangingTabTreatInfo)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CPatMan message handlers

BOOL CPatMan::OnInitDialog() 
{
	CDialog::OnInitDialog();

	HWND hWnd = GetSafeHwnd();
	ShowWindow(SW_MAXIMIZE);

	//  Close button
	m_btnClose.LoadBitmaps(IDB_BITMAP_CLOSE);
	m_btnClose.SizeToContent();

	// 6 tabs
	m_pageZhusu.Create(CZhusuPage::IDD,						this,	TAB_INDEX_ZHUSU);
	m_pageHisNow.Create(CHisNowPage::IDD,					this,	TAB_INDEX_NOWHIST);
	m_pageHisPast.Create(CHisPastPage::IDD,					this,	TAB_INDEX_PASTHIST);
	m_pageBodyCheck.Create(CBodyCheckPage::IDD,				this,	TAB_INDEX_BODYCHECK);
	m_pageFirstDiag.Create(CFirstDiagPage::IDD,				this,	TAB_INDEX_1STDIAG);
	m_pageSubsqtDiag.Create(CSubsqtDiagPage::IDD,			this,	TAB_INDEX_SUBSDIAG);
	m_pageSubSqtDiagQuery.Create(CSubsqDiagQueryPage::IDD,	this,	TAB_INDEX_SDQUERY);

	m_tabTreat.InsertItem(TCIF_TEXT|TCIF_PARAM, 0, GetResString(IDS_TABTITLE_ZHUSU),			0, (LPARAM)&m_pageZhusu);
	m_tabTreat.InsertItem(TCIF_TEXT|TCIF_PARAM, 1, GetResString(IDS_TABTITLE_NOWHIST),			0, (LPARAM)&m_pageHisNow);
	m_tabTreat.InsertItem(TCIF_TEXT|TCIF_PARAM, 2, GetResString(IDS_TABTITLE_PASTHIST),			0, (LPARAM)&m_pageHisPast);
	m_tabTreat.InsertItem(TCIF_TEXT|TCIF_PARAM, 3, GetResString(IDS_TABTITLE_BODYCHECK),		0, (LPARAM)&m_pageBodyCheck);
	m_tabTreat.InsertItem(TCIF_TEXT|TCIF_PARAM, 4, GetResString(IDS_TABTITLE_FIRSTDIAG),		0, (LPARAM)&m_pageFirstDiag);
	m_tabTreat.InsertItem(TCIF_TEXT|TCIF_PARAM, 5, GetResString(IDS_TABTITLE_SUBSEDIAG),		0, (LPARAM)&m_pageSubsqtDiag);
	m_tabTreat.InsertItem(TCIF_TEXT|TCIF_PARAM, 6, GetResString(IDS_TABTITLE_SUBSQDIAG_QUERY),	0, (LPARAM)&m_pageSubSqtDiagQuery);

	m_tabTreat.SetItemSize(150);

	RECT rectTab = {0};
	m_tabTreat.GetWindowRect(&rectTab);
	ClientToScreen(&rectTab);
	
	RECT rectItem = {0};
	m_tabTreat.GetItemRect(0, &rectItem);

	VERIFY(m_pageZhusu.SetWindowPos(&m_tabTreat, rectTab.left + 5, rectTab.top + rectItem.bottom + 5, rectTab.right - rectTab.left - 25, rectTab.bottom - rectTab.top - 35, SWP_SHOWWINDOW));
	VERIFY(m_pageHisNow.SetWindowPos(&m_tabTreat, rectTab.left + 5, rectTab.top + rectItem.bottom + 5, rectTab.right - rectTab.left - 25, rectTab.bottom - rectTab.top - 35, SWP_HIDEWINDOW));
	VERIFY(m_pageHisPast.SetWindowPos(&m_tabTreat, rectTab.left + 5, rectTab.top + rectItem.bottom + 5, rectTab.right - rectTab.left - 25, rectTab.bottom - rectTab.top - 35, SWP_HIDEWINDOW));
	VERIFY(m_pageBodyCheck.SetWindowPos(&m_tabTreat, rectTab.left + 5, rectTab.top + rectItem.bottom + 5, rectTab.right - rectTab.left - 25, rectTab.bottom - rectTab.top - 35, SWP_HIDEWINDOW));
	VERIFY(m_pageFirstDiag.SetWindowPos(&m_tabTreat, rectTab.left + 5, rectTab.top + rectItem.bottom + 5, rectTab.right - rectTab.left - 25, rectTab.bottom - rectTab.top - 35, SWP_HIDEWINDOW));
	VERIFY(m_pageSubsqtDiag.SetWindowPos(&m_tabTreat, rectTab.left + 5, rectTab.top + rectItem.bottom + 5, rectTab.right - rectTab.left - 25, rectTab.bottom - rectTab.top - 35, SWP_HIDEWINDOW));
	VERIFY(m_pageSubSqtDiagQuery.SetWindowPos(&m_tabTreat, rectTab.left + 5, rectTab.top + rectItem.bottom + 5, rectTab.right - rectTab.left - 25, rectTab.bottom - rectTab.top - 35, SWP_HIDEWINDOW));

	CLinkInputNode::EnableInputs(FALSE, IBT_AllType, this);
	CLinkInputNode::EnableInputs(FALSE, IBT_AllType, &m_pageZhusu);
	CLinkInputNode::EnableInputs(FALSE, IBT_AllType, &m_pageHisNow);
	CLinkInputNode::EnableInputs(FALSE, IBT_AllType, &m_pageHisPast);
	CLinkInputNode::EnableInputs(FALSE, IBT_AllType, &m_pageBodyCheck);
	CLinkInputNode::EnableInputs(FALSE, IBT_AllType, &m_pageFirstDiag);
	CLinkInputNode::EnableInputs(FALSE, IBT_AllType, &m_pageSubsqtDiag);
	CLinkInputNode::EnableInputs(FALSE, IBT_AllType, &m_pageSubSqtDiagQuery);

	m_edtMedicaRecordNo.EnableWindow(TRUE);
	m_edtName.EnableWindow(TRUE);
	m_edtSerialNo.EnableWindow(TRUE);

	CLinkInputNode::EnableCheckValid(TRUE, IBT_AllType, this);
	GetDlgItem(IDB_EDIT_PATIENT_INFO)->EnableWindow(FALSE);
	GetDlgItem(IDC_EDIT_1ST_CLINIC_TIME)->EnableWindow(FALSE);	

	m_tabTreat.SetActiveTabColor(ACTIVE_TAB_COLOR);
	m_tabTreat.SetCurSel(TAB_INDEX_ZHUSU);

	//  Start from 1, to leave the 0th tab be enable. if there is no tab enable, the CTabCtrlEx will enum all tabs, that cause 
	//  all tab's Prepare() to be called 
	for(int i = 1; i < m_tabTreat.GetItemCount(); i++)
		EnableTab(i, FALSE);

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}


void CPatMan::OnSelchangingTabTreatInfo(NMHDR* pNMHDR, LRESULT* pResult) 
{
	int nCurSel = m_tabTreat.GetCurSel();
	
	for(int i = 0; i < m_tabTreat.GetItemCount(); i++)
	{
		TCITEM tcItem = {0};
		tcItem.mask = TCIF_PARAM;
		m_tabTreat.GetItem(i, &tcItem);
		
		CPageDialog* pPage = (CPageDialog*)tcItem.lParam;
		if(pPage && i == nCurSel)
		{
			pPage->ClearUp();
		}
	}

	*pResult = 0;
}

void CPatMan::OnSelchangeTabTreatInfo(NMHDR* pNMHDR, LRESULT* pResult) 
{
	int nCurSel = m_tabTreat.GetCurSel();

	for(int i = 0; i < m_tabTreat.GetItemCount(); i++)
	{
		TCITEM tcItem = {0};
		tcItem.mask = TCIF_PARAM;
		m_tabTreat.GetItem(i, &tcItem);
		
		CPageDialog* pPage = (CPageDialog*)tcItem.lParam;
		if(pPage)
		{
			if(i == nCurSel)
				pPage->Prepare();

			pPage->ShowWindow(i == nCurSel ? SW_SHOW : SW_HIDE);
		}
	}

	*pResult = 0;
}

void CPatMan::OnBitmapClose() 
{
	for(int j = 0; j < m_tabTreat.GetItemCount(); j++)
	{
		TCITEM tcItem = {0};
		tcItem.mask = TCIF_PARAM;
		m_tabTreat.GetItem(j, &tcItem);
		
		CPageDialog* pPage = (CPageDialog*)tcItem.lParam;
		if(pPage)
		{
			pPage->ClearUp();
			pPage->ClearData();
		}
	}

	EndDialog(IDCANCEL);
}

void CPatMan::OnNewPatientInfo() 
{
	//  get the record count
	CString strSQL = _T("SELECT COUNT(*) AS RecCnt FROM PatientInfo");
	CGYDataSet dsRecCnt(strSQL);

	if(dsRecCnt.IsEOF())
	{
		DataErrorMsgBox(__FILE__, __LINE__, strSQL, dsRecCnt.GetLastErrorString());
		return;
	}

	CString strRecCnt;
	dsRecCnt.GetFieldValue(_T("RecCnt"), strRecCnt);
	
	ClearPatientData();

	int nIndex = _ttoi(strRecCnt);
	strRecCnt.Format(_T("%d"), nIndex + 1);
	GetDlgItem(IDC_EDIT_SERIAL_NO)->SetWindowText(strRecCnt);

	CLinkInputNode::EnableInputs(TRUE, IBT_AllType, this);

	GetDlgItem(IDC_EDIT_SERIAL_NO)->EnableWindow(FALSE);
	GetDlgItem(IDC_EDIT_1ST_CLINIC_TIME)->EnableWindow(FALSE);	
	GetDlgItem(IDB_EDIT_PATIENT_INFO)->EnableWindow(FALSE);
	GetDlgItem(IDC_EDIT_1ST_CLINIC_DOCTOR)->SetWindowText(GetApp()->GetUserRealName());
	GetDlgItem(IDC_EDIT_1ST_CLINIC_DOCTOR)->EnableWindow(FALSE);

	CLinkInputNode::EnableInputs(TRUE, IBT_AllType, &m_pageZhusu);
	CLinkInputNode::EnableInputs(TRUE, IBT_AllType, &m_pageHisNow);
	CLinkInputNode::EnableInputs(TRUE, IBT_AllType, &m_pageHisPast);
	CLinkInputNode::EnableInputs(TRUE, IBT_AllType, &m_pageBodyCheck);
	CLinkInputNode::EnableInputs(TRUE, IBT_AllType, &m_pageFirstDiag);
	CLinkInputNode::EnableInputs(FALSE, IBT_AllType, &m_pageSubsqtDiag);

	m_tabTreat.SetActiveTabColor(ACTIVE_TAB_COLOR);
	for(int j = 0; j < m_tabTreat.GetItemCount(); j++)
	{
		TCITEM tcItem = {0};
		tcItem.mask = TCIF_PARAM;
		m_tabTreat.GetItem(j, &tcItem);
		
		CPageDialog* pPage = (CPageDialog*)tcItem.lParam;
		if(pPage)
		{
			pPage->ClearUp();
			pPage->ClearData();
			pPage->EnableInputControls(TRUE);
		}

		EnableTab(j, j == TAB_INDEX_ZHUSU);
	}
	
	TCHAR szTabTitle[MAX_PATH] = {0};
	_tcscpy(szTabTitle, GetResString(IDS_TABTITLE_SUBSEDIAG));
	SetTabTitle(TAB_INDEX_SUBSDIAG, szTabTitle);

	m_cmbGender.SetCurSel(0);
	m_edtMedicaRecordNo.SetFocus();

	m_bPatInfoSaved = FALSE;
	GetDlgItem(IDB_NEW_PATIENT_INFO)->EnableWindow(FALSE);
	GetDlgItem(IDB_CANCEL_PATIENT_INFO)->EnableWindow(TRUE);
}

void CPatMan::OnOK()
{

}

BOOL CPatMan::CheckPatientInfoValid()
{
	for(int i = 0; i < ARRAY_ELE_COUNT(s_InputFieldArray); i++)
	{
		switch(s_InputFieldArray[i].dwCtrlType)
		{
		case IBT_EditBox:
			{
				CLinkEdit* pLinkEdit = (CLinkEdit*)s_InputFieldArray[i].pLinkCtrl;
				if(!pLinkEdit->CheckDataValidFirst() || !pLinkEdit->CheckCtrlDataValid())
				{
					pLinkEdit->SetFocus();
					return FALSE;
				}
			}
			break;
		case IBT_EditDate:
			{
				CLinkDateEdit* pLinkDate = (CLinkDateEdit*)s_InputFieldArray[i].pLinkCtrl;
				if(!pLinkDate->CheckDataValidFirst() || !pLinkDate->CheckCtrlDataValid())
				{
					pLinkDate->SetFocus();
					return FALSE;
				}
			}
			break;
		case IBT_ComboBox:
			{
				CLinkComboBox* pLinkCombo = (CLinkComboBox*)s_InputFieldArray[i].pLinkCtrl;
				if(!pLinkCombo->CheckDataValidFirst() || !pLinkCombo->CheckCtrlDataValid())
				{
					pLinkCombo->SetFocus();
					return FALSE;
				}
			}
			break;
		}
	}

	return TRUE;
}


BOOL CPatMan::SavePatientTable()
{
	CString strSN = m_edtSerialNo.GetControlData();
	CString strSQL;
	strSQL.Format(_T("SELECT SerialNo FROM PatientInfo WHERE SerialNo=%s"), strSN);
	CGYDataSet tblPat(strSQL);
	if(!tblPat.IsEOF())
	{
		strSQL = _T("SELECT MAX(SerialNo) AS MaxSN FROM PatientInfo");
		tblPat.OpenTable(strSQL);

		int nNewSN = _ttoi(strSN);
		if(!tblPat.IsEOF())
		{
			tblPat.GetFieldValue(_T("MaxSN"), strSN);
			nNewSN = _ttoi(strSN);
		}

		strSN.Format(_T("%d"), nNewSN + 1);
		m_edtSerialNo.SetWindowText(strSN);
	}

	CString strNameList, strValueList;
	for(CLinkInputNode* pNode = CLinkInputNode::GetHeadNode(); pNode; pNode = pNode->GetNextNode())
	{
		CWnd* pCtrl = pNode->GetCtrl();
		if(pCtrl && pCtrl->GetParent() == this)
		{
			if(pNode->GetCtrlType() == IBT_EditBox)
			{
				CLinkEdit* pLinkEdit = (CLinkEdit*)pCtrl;

				strNameList		+= pLinkEdit->GetCtrlFieldName() + _T(",");

				if(pLinkEdit->GetCtrlFieldName() == _T("FirstClinicDoctor"))
					strValueList += _T("'") + GetApp()->GetUserName() + _T("',");
				else
					strValueList += pLinkEdit->GetCtrlFieldValue() + _T(",");
			}
			
			if(pNode->GetCtrlType() == IBT_EditDate)
			{
				CLinkDateEdit* pLinkDate = (CLinkDateEdit*)pCtrl;
				
				strNameList		+= pLinkDate->GetCtrlFieldName() + _T(",");
				strValueList	+= pLinkDate->GetCtrlFieldValue() + _T(",");
			}
			
			if(pNode->GetCtrlType() == IBT_ComboBox)
			{
				CLinkComboBox* pLinkCombo = (CLinkComboBox*)pCtrl;
				
				strNameList		+= pLinkCombo->GetCtrlFieldName() + _T(",");
				strValueList	+= pLinkCombo->GetCtrlFieldValue() + _T(",");
			}
		}
	}

	strNameList += _T("DiagProgress");
	strValueList += _T("-1");

	strNameList.TrimRight(_T(","));
	strValueList.TrimRight(_T(","));

	strSQL.Format(_T("INSERT INTO PatientInfo (%s) VALUES (%s)"), strNameList, strValueList);
	return tblPat.ExecuteSQL(strSQL);
}

void CPatMan::AfterSavePatientTable()
{
	CLinkInputNode::EnableInputs(FALSE, IBT_AllType, this);
	
	m_edtMedicaRecordNo.EnableWindow(TRUE);
	m_edtName.EnableWindow(TRUE);
	m_edtSerialNo.EnableWindow(TRUE);

	
	m_bPatInfoSaved = TRUE;

	DWORD dwSN = _ttoi(m_edtSerialNo.GetControlData(FALSE, FALSE));
	GetApp()->SetCurSN(dwSN);

	GetApp()->SetCurMRN(m_edtMedicaRecordNo.GetControlData(TRUE, FALSE));
	m_strCurrentName = m_edtName.GetControlData(TRUE, FALSE);
	m_strCurrentSN = m_edtSerialNo.GetControlData();

	GetDlgItem(IDB_EDIT_PATIENT_INFO)->EnableWindow(TRUE);
	GetDlgItem(IDB_NEW_PATIENT_INFO)->EnableWindow(TRUE);
	GetDlgItem(IDB_CANCEL_PATIENT_INFO)->EnableWindow(FALSE);
}

BOOL CPatMan::ShowTableValues(CLinkEdit* pLinkEdit, CString strFieldName, CString strFieldValue)
{
	//  Show patient info
	if(!ShowTablePatientInfo(pLinkEdit, strFieldName, strFieldValue))
		return FALSE;

	CString strMRN = GetApp()->GetCurMRN();
	if(strFieldName == s_InputFieldArray[0].szFieldName)
		strMRN = strFieldValue;

	//  Show info in every tab
	for(int i = 0; i < m_tabTreat.GetItemCount(); i++)
	{
		TCITEM tcItem = {0};
		tcItem.mask = TCIF_PARAM;
		m_tabTreat.GetItem(i, &tcItem);
		
		CPageDialog* pPage = (CPageDialog*)tcItem.lParam;
		if(pPage)
			pPage->ShowTableData(strMRN);
	}

	return TRUE;
}

BOOL CPatMan::ShowTablePatientInfo(CLinkEdit* pLinkEdit, CString strFieldName, CString strFieldValue)
{
	CString strSQL;
	strFieldValue.Replace(_T("'"), _T("''"));
	strSQL.Format(_T("SELECT * FROM PatientInfo WHERE %s='%s'"), strFieldName, strFieldValue);
	
	CGYDataSet tblPatInfo;
	tblPatInfo.OpenTable(strSQL);

	int nRecCnt = 0;
	for(; !tblPatInfo.IsEOF(); tblPatInfo.MoveNext(), nRecCnt++);

	if(nRecCnt <= 0)
	{
		//  Do nothing
		return FALSE;
	}
	else if(nRecCnt == 1)
	{
		return ShowPatientInfoFromTable(&tblPatInfo, 0);
	}
	else
	{
		CPatientSelectDlg dlg(&tblPatInfo);
		if(dlg.DoModal() == IDOK)
		{
			int nIndex = dlg.GetSelectIndex();
			return ShowPatientInfoFromTable(&tblPatInfo, nIndex);
		}
	}

	return TRUE;
}

BOOL CPatMan::KeyFieldsCheck(LPVOID pParam)
{
	if(pParam)
	{
		INPUT_FIELD_INFO* pFieldInfo = (INPUT_FIELD_INFO*)pParam;
		CLinkEdit* pEdit = (CLinkEdit*)pFieldInfo->pLinkCtrl;
		if(pEdit)
		{
			CString strNowText = pEdit->GetControlData(TRUE, FALSE);
			CPatMan* pThis = (CPatMan*)pEdit->GetParent();
			if(pThis)
			{
				if(pThis->IsPatientInfoSaved())
				{
					INPUT_FIELD_INFO* pFieldInfo = pEdit->GetFieldInfo();
					if(pFieldInfo && pFieldInfo->szFieldName)
					{
						if(strNowText.IsEmpty())
						{
							return TRUE;
						}
						else
						{
							BOOL bShowValue = FALSE;

							if(pParam == s_InputFieldArray[0].pLinkCtrl && strNowText != GetApp()->GetCurMRN())
								bShowValue = TRUE;
							else if(pParam == s_InputFieldArray[1].pLinkCtrl && strNowText != pThis->m_strCurrentName)
								bShowValue = TRUE;
							else if(pParam == s_InputFieldArray[2].pLinkCtrl && strNowText != pThis->m_strCurrentSN)
								bShowValue = TRUE;

							if(strNowText != pEdit->GetBeforeValue())
								bShowValue = TRUE;

							if(bShowValue)
							{
								if(!pThis->ShowTableValues(pEdit, pFieldInfo->szFieldName, strNowText))
								{
									pThis->EnableTabAndCtrlsForNone();
									pThis->ClearPatientData();

									pThis->GetDlgItem(IDB_EDIT_PATIENT_INFO)->EnableWindow(FALSE);
									GetApp()->SetCurMRN(_T(""));

									return FALSE;
								}

								if(!pThis->EnableTabAndCtrlsForQuery())
								{
									pThis->GetDlgItem(IDB_EDIT_PATIENT_INFO)->EnableWindow(FALSE);
									pThis->ClearPatientData();
									return FALSE;
								}
								
								pThis->GetDlgItem(IDB_EDIT_PATIENT_INFO)->EnableWindow(TRUE);

								//  return FALSE, so the cursor will NOT go to the next
							}
						}
					}
				}
				else
				{
					BOOL bValid = pEdit->CheckDataValidFirst();
					if(bValid)
					{
						//  New a patient
						INPUT_FIELD_INFO* pFieldInfo = pEdit->GetFieldInfo();
						if(pFieldInfo && _tcsicmp(pFieldInfo->szFieldName, _T("MedicalRecordNo")) == 0)
						{
							return pThis->CheckMRNDuplicate();
						}
					}

					return bValid;
				}
			}
		}
	}
	
	return FALSE;
}

BOOL CPatMan::ShowPatientInfoFromTable(CGYDataSet* pDataSet, int nIndex)
{
	if(pDataSet->GetRecordCount() <= 0)
		return FALSE;

	int nMove = 0;
	for(pDataSet->MoveFirst(); !pDataSet->IsEOF() && nMove < nIndex; pDataSet->MoveNext(), nMove++);

	for(int i = 0; i < ARRAY_ELE_COUNT(s_InputFieldArray); i++)
	{
		switch(s_InputFieldArray[i].dwCtrlType)
		{
		case IBT_EditBox:
			{
				CLinkEdit* pLinkEdit = (CLinkEdit*)s_InputFieldArray[i].pLinkCtrl;
				CString strValue;
				pDataSet->GetFieldValue(s_InputFieldArray[i].szFieldName, strValue);

				if(_tcsicmp(s_InputFieldArray[i].szFieldName, _T("FirstClinicDoctor")) == 0)
					strValue = GetUserRealNameFromUserName(strValue);

				pLinkEdit->SetWindowText(strValue);
			}
			break;
		case IBT_EditDate:
			{
				CLinkDateEdit* pLinkDate = (CLinkDateEdit*)s_InputFieldArray[i].pLinkCtrl;
				CString strValue;
				pDataSet->GetFieldValue(s_InputFieldArray[i].szFieldName, strValue);
				strValue = strValue.Left(10);
				pLinkDate->SetWindowText(strValue);
			}
			break;
		case IBT_ComboBox:
			{
				CLinkComboBox* pLinkCombo = (CLinkComboBox*)s_InputFieldArray[i].pLinkCtrl;
				CString strValue;
				pDataSet->GetFieldValue(s_InputFieldArray[i].szFieldName, strValue);
				pLinkCombo->SetCurSel(_ttoi(strValue));
			}
			break;
		}
	}
	
	DWORD dwSN = _ttoi(m_edtSerialNo.GetControlData(FALSE, FALSE));
	GetApp()->SetCurSN(dwSN);
	GetApp()->SetCurMRN(m_edtMedicaRecordNo.GetControlData(FALSE, FALSE));
	m_strCurrentName = m_edtName.GetControlData(TRUE, FALSE);
	m_strCurrentSN = m_edtSerialNo.GetControlData();

	GetDlgItem(IDB_EDIT_PATIENT_INFO)->EnableWindow(TRUE);

	return TRUE;
}

void CPatMan::OnEditPatientInfo() 
{
	CPatInfoEditDlg dlg(s_InputFieldArray, ARRAY_ELE_COUNT(s_InputFieldArray));
	dlg.DoModal();
}

BOOL CPatMan::SavePatMedInfo()
{
	CWaitCursor wait;

	//  check the MRN duplication
	if(!IsPatientInfoSaved())
	{
		if(!CheckMRNDuplicate())
			return FALSE;
	}

	//  In fact, the following statement is called only by Zhusu
	if(!IsPatientInfoSaved())
	{
		if(!CheckPatientInfoValid())
			return FALSE;

		if(!SavePatientTable())
			return FALSE;

		AfterSavePatientTable();
	}

	return TRUE;
}

void CPatMan::OnCancelPatientInfo() 
{
	if(GYMsgBox(IDS_PAT_CANCEL_NEW_PAT, MB_YESNO|MB_ICONQUESTION) != IDYES)	
		return;

	ClearPatientData();
	for(int i = 0; i < m_tabTreat.GetItemCount(); i++)
	{
		TCITEM tcItem = {0};
		tcItem.mask = TCIF_PARAM;
		m_tabTreat.GetItem(i, &tcItem);
		
		CPageDialog* pPage = (CPageDialog*)tcItem.lParam;
		if(pPage) 
		{
			pPage->ClearData();
			pPage->EnableInputControls(FALSE);
		}
	}

	m_bPatInfoSaved = TRUE;

	CLinkInputNode::EnableInputs(FALSE, IBT_AllType, this);
	m_edtMedicaRecordNo.EnableWindow(TRUE);
	m_edtName.EnableWindow(TRUE);
	m_edtSerialNo.EnableWindow(TRUE);

	GetDlgItem(IDB_NEW_PATIENT_INFO)->EnableWindow(TRUE);
	GetDlgItem(IDB_CANCEL_PATIENT_INFO)->EnableWindow(FALSE);	
}

BOOL CPatMan::ClearPatientData()
{
	for(int i = 0; i < ARRAY_ELE_COUNT(s_InputFieldArray); i++)
	{
		switch(s_InputFieldArray[i].dwCtrlType)
		{
		case IBT_EditBox:
			{
				CLinkEdit* pLinkEdit = (CLinkEdit*)s_InputFieldArray[i].pLinkCtrl;
				pLinkEdit->SetWindowText(_T(""));
			}
			break;
		case IBT_EditDate:
			{
				CLinkDateEdit* pLinkDate = (CLinkDateEdit*)s_InputFieldArray[i].pLinkCtrl;
				pLinkDate->SetToday();
			}
			break;
		case IBT_ComboBox:
			{
				CLinkComboBox* pLinkCombo = (CLinkComboBox*)s_InputFieldArray[i].pLinkCtrl;
				pLinkCombo->SetCurSel(0);
			}
			break;
		}
	}
	
	return TRUE;
}


CString CPatMan::GetUserRealNameFromUserName(CString strUserName)
{
	if(strUserName.CompareNoCase(GetApp()->GetUserName()) == 0)
		return GetApp()->GetUserRealName();

	CString strSQL;
	strSQL.Format(_T("SELECT RealName FROM UserInfo WHERE UserName='%s'"), strUserName);

	CGYDataSet setUserInfo(strSQL);
	if(!setUserInfo.IsEOF())
	{
		CString strRealName;
		setUserInfo.GetFieldValue(_T("RealName"), strRealName);
		return strRealName;
	}

	return _T("");
}

CPageDialog* CPatMan::GetTabPage(DWORD dwPageIndex)
{
	if(dwPageIndex >= 0 && dwPageIndex < m_tabTreat.GetItemCount())
	{
		TCITEM tcItem = {0};
		tcItem.mask = TCIF_PARAM;
		m_tabTreat.GetItem(dwPageIndex, &tcItem);
		
		CPageDialog* pPage = (CPageDialog*)tcItem.lParam;
		return pPage;
	}

	return NULL;
}

BOOL CPatMan::EnableTabAndCtrlsForQuery()
{
	CString strMRN = GetApp()->GetCurMRN();

	CString strSQL;
	strSQL.Format(_T("SELECT DiagProgress FROM PatientInfo WHERE MedicalRecordNo='%s'"), strMRN);
	CGYDataSet setPatInfo(strSQL);
	
	if(setPatInfo.IsEOF())
		return FALSE;
	
	CString strDiagProgress;
	setPatInfo.GetFieldValue(_T("DiagProgress"), strDiagProgress);
	
	int nDiagProgress = _ttoi(strDiagProgress);
	ASSERT(nDiagProgress >= 0);

	//  check whether the progress is correct
	BOOL bLastSDiagIsDraft = FALSE;
	strSQL.Format(_T("SELECT DiagSN, IsDraft FROM DiagRecord WHERE MedicalRecordNo='%s' ORDER BY DiagSN DESC LIMIT 1"), strMRN);
	CGYDataSet setDiagRec(strSQL);
	if(setDiagRec.IsEOF())
	{
		if(nDiagProgress >= TAB_INDEX_1STDIAG)
		{
			//  no diagnose record, but the progress is more than 1st diagnose, correct it
			nDiagProgress = TAB_INDEX_ZHUSU;
			strSQL.Format(_T("UPDATE PatientInfo SET DiagProgress=%d WHERE MedicalRecordNo='%s'"), nDiagProgress, strMRN);
			setDiagRec.ExecuteSQL(strSQL);
		}
	}
	else
	{
		CString strCorrectDiagSN;
		setDiagRec.GetFieldValue(_T("DiagSN"), strCorrectDiagSN);
		int nCorrectDiagSN = _ttoi(strCorrectDiagSN);

		if(nCorrectDiagSN == 0)
		{
			if(nDiagProgress != TAB_INDEX_1STDIAG)
			{
				//  correct it to 1st diagnose
				nDiagProgress = TAB_INDEX_1STDIAG;
				strSQL.Format(_T("UPDATE PatientInfo SET DiagProgress=%d WHERE MedicalRecordNo='%s'"), nDiagProgress, strMRN);
				setDiagRec.ExecuteSQL(strSQL);
			}
		}
		else if(nCorrectDiagSN > 0)
		{
			CString strIsDraft;
			setDiagRec.GetFieldValue(_T("IsDraft"), strIsDraft);
			bLastSDiagIsDraft = (strIsDraft == _T("1"));

			if(nDiagProgress != TAB_INDEX_SUBSDIAG)
			{
				//  correct it to subsequent diagnose
				nDiagProgress = TAB_INDEX_SUBSDIAG;
				strSQL.Format(_T("UPDATE PatientInfo SET DiagProgress=%d WHERE MedicalRecordNo='%s'"), nDiagProgress, strMRN);
				setDiagRec.ExecuteSQL(strSQL);
			}
		}
	}

	//  enable/disable tabs
	int nTabCount = m_tabTreat.GetItemCount();
	if(nDiagProgress < TAB_INDEX_1STDIAG)
	{
		for(int i = 0; i < nTabCount; i++)
			EnableTab(i, i <= (nDiagProgress + 1));
	}
	else if(nDiagProgress == TAB_INDEX_1STDIAG)
	{
		for(int i = 0; i < nTabCount; i++)
			EnableTab(i, i != TAB_INDEX_SUBSDIAG);
	}
	else
	{
		for(int i = 0; i < nTabCount; i++)
			EnableTab(i, TRUE);
	}

	for(int j = 0; j < m_tabTreat.GetItemCount(); j++)
	{
		TCITEM tcItem = {0};
		tcItem.mask = TCIF_PARAM;
		m_tabTreat.GetItem(j, &tcItem);
		
		CPageDialog* pPage = (CPageDialog*)tcItem.lParam;

		if(nDiagProgress < TAB_INDEX_1STDIAG)
		{
			pPage->EnableInputControls(j == (nDiagProgress + 1));
		}
		else if(nDiagProgress == TAB_INDEX_1STDIAG)
		{
			pPage->EnableInputControls(j == TAB_INDEX_SDQUERY);
		}
		else
		{
			if(bLastSDiagIsDraft)
				pPage->EnableInputControls(j >= TAB_INDEX_SUBSDIAG);
			else
				pPage->EnableInputControls(j == TAB_INDEX_SDQUERY);
		}
	}

	return TRUE;
}

BOOL CPatMan::EnableTabAndCtrlsForNone()
{
	for(int j = 0; j < m_tabTreat.GetItemCount(); j++)
	{
		TCITEM tcItem = {0};
		tcItem.mask = TCIF_PARAM;
		m_tabTreat.GetItem(j, &tcItem);
		
		CPageDialog* pPage = (CPageDialog*)tcItem.lParam;
		if(pPage)
		{
			pPage->ClearData();
			pPage->EnableInputControls(FALSE);
		}
		
		EnableTab(j, j == TAB_INDEX_ZHUSU);
	}
	
	m_tabTreat.SetCurSel(TAB_INDEX_ZHUSU);

	return TRUE;
}


BOOL CPatMan::LostFocusCheck(LPVOID pParam)
{
	return TRUE;
}

BOOL CPatMan::DateOfBirthCheck(LPVOID pParam)
{
	if(pParam)
	{
		INPUT_FIELD_INFO* pFieldInfo = (INPUT_FIELD_INFO*)pParam;
		CLinkDateEdit* pDateOfBirth = (CLinkDateEdit*)pFieldInfo->pLinkCtrl;
		if(pDateOfBirth)
		{
			CString strDateOfBirth = pDateOfBirth->GetControlData();
			
			int nYear = _ttoi(strDateOfBirth.Left(4));
			int nMonth = _ttoi(strDateOfBirth.Mid(5, 2));
			int nDay = _ttoi(strDateOfBirth.Right(2));
			
			if(!IsValidDateTime(nYear, nMonth, nDay, 0, 0, 0))
			{
				GYMsgBox(IDS_PAT_INVALID_DATE, MB_OK|MB_ICONINFORMATION);
				return FALSE;
			}
			
			CPatMan* pParent = (CPatMan*)pDateOfBirth->GetParent();
			if(pParent)
			{
				CString str1stDiagDay = pParent->m_edt1stClinicDate.GetControlData();
				if(strDateOfBirth >= str1stDiagDay)
				{
					GYMsgBox(IDS_PAT_BIRTH_LESS_1STDIAGDAY, MB_OK|MB_ICONINFORMATION);
					return FALSE;
				}
				
				return TRUE;
			}
		}
	}

	return FALSE;
}

void CPatMan::SetTabTitle(int nTabIndex, TCHAR* szTitle)
{
	TCITEM tcItem		= {0};
	tcItem.mask			= TCIF_TEXT;
	tcItem.pszText		= szTitle;
	tcItem.cchTextMax	= _tcslen(szTitle) + 1;

	m_tabTreat.SetItem(nTabIndex, &tcItem);
}

void CPatMan::QuitPatMan()
{
	OnBitmapClose();
}

BOOL CPatMan::CheckMRNDuplicate()
{
	CString strMRN = m_edtMedicaRecordNo.GetControlData();
	
	CString strSQL;
	strSQL.Format(_T("SELECT Name, Gender, DateOfBirth, HomeAddress FROM PatientInfo WHERE MedicalRecordNo='%s'"), strMRN);
	
	CGYDataSet setPatInfo(strSQL);
	if(!setPatInfo.IsEOF())
	{
		CString strName, strGender, strDateOfBirth, strHomeAddress;
		setPatInfo.GetFieldValue(_T("Name"), strName);
		setPatInfo.GetFieldValue(_T("Gender"), strGender);
		setPatInfo.GetFieldValue(_T("DateOfBirth"), strDateOfBirth);
		setPatInfo.GetFieldValue(_T("HomeAddress"), strHomeAddress);
		
		strGender = (strGender == _T("0")) ? GetResString(IDS_PAT_MALE) : GetResString(IDS_PAT_FEMALE);
		strDateOfBirth = strDateOfBirth.Left(10);
		
		CString strMedicalCardDup = GetResString(IDS_PAT_MEDCARDNO_DUP);
		
		CString strInfo;
		strInfo.Format(strMedicalCardDup, strMRN, strName, strGender, strDateOfBirth, strHomeAddress);
		GYMsgBox(strInfo, MB_ICONINFORMATION|MB_OK);
		
		return FALSE;
	}

	return TRUE;
}